#============================================================
# Create Time:			2021-11-02 08:36:27
# Last modify:			2021-11-02 07:19:12
# Writer:				Wenhao	wh.wenhao@foxmail.com
# File Name:			server.py
# File Type:			PY Source File
# Tool:					Mac -- vim & python
# Information:
#============================================================

import os
import sys
import socket
import argparse
import threading
from queue import Queue

from protocal import send_data, recv_data
sys.path.append('../Hw3')
from parse import GPRMC, GPGGA

def build_socket():
    address = ('0.0.0.0', 5678)  # 服务端地址和端口
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(address)  # 绑定服务端地址和端口
    s.listen(5)
    return s

def session(conn, addr, queue: Queue):
    print('[+] Connected with', addr)
    client_info = '站点：%s'%(addr[0])
    while True:
        line = recv_data(conn) # 按照规定的数据传输协议，读取数据
        if not line:
            conn.close()
            print('[closed][%s:%d]'%(*addr,))
            break
        print('[got][%s:%d] %s'%(*addr, line))
        # 读取的数据是gps-example.txt中的每一行的内容，按照实验三的处理逻辑
        # 从中取得格式化后的文本。
        if line.startswith('$GPGGA'):
            gpgga = GPGGA(line)
            height = '高度：%s'%(gpgga.get_height())
        elif line.startswith('$GPRMC'):
            gprmc = GPRMC(line)
            gps_info = gprmc.data_formated()
            gps_info = '%s\n%s%s\n'%(client_info, gps_info, height)
            # 已经得到了一条GPS记录，将这条记录传回给客户端
            send_data(conn, gps_info)
            # 将这条GPS记录放入写队列中，专门负责数据存储的线程会处理queue中的数据
            queue.put(gps_info)

def save_gps_data(queue: Queue, fname='gps-reports.txt'):
    foutput = open(fname, 'w', encoding='utf-8')
    while True:
        content = queue.get()
        queue.task_done()
        foutput.write('%s\n'%(content))

if __name__ == '__main__':
    # 开启server，监听5678端口
    tcp_socket = build_socket()
    # 用此队列收集待存储GPS记录。
    # Queue线程安全。
    queue = Queue(10)
    # 开启一个线程，从queue中取出待存储记录，并写入文件
    threading.Thread(target=save_gps_data, args=(queue, )).start()
    while True:
        # 与一个客户端建立连接
        conn, addr = tcp_socket.accept()
        # 开启一个线程，处理与此客户端的通信。
        # 可以同时与多个客户端通信。
        t = threading.Thread(target=session, args=(conn, addr, queue))
        t.start()
